home *** CD-ROM | disk | FTP | other *** search
- /*
- Seconds.c
-
- s=Seconds();
- returns the number of seconds (as a double, with 20 µs or better
- accuracy) since the computer started up.
-
- If possible, we use the new UpTime routine, which uses the PPC's
- internal clock to get an accurate time with 20 nanosecond or better
- precision, but it's only available on PCI PowerMacs. Otherwise we use
- the Microseconds routine, which has 20 microseconds precision, and is
- part of Mac OS 7.
-
- UpTime offers stable timing even when interrupts are blocked (e.g. by
- calls to cscSetEntries). It is my unconfirmed impression that
- Microseconds advances at a reduced rate when we're repeatedly calling
- cscSetEntries on my PowerMac 7500.
-
- Microseconds() is documented in "Inside Mac: OS Utilities".
-
- UpTime is documented in "Designing PCI Cards and Drivers for Power
- Macintosh Computers".
-
- UpTime and Microseconds are briefly described in Martin Minow (1996)
- Timing on the Macintosh, develop 26.
- <http://devworld.apple.com/dev/techsupport/develop/issue26/minow.html>
-
- The shared library DriverServicesLib must be weak linked with this
- project, when compiling for ppc; it's not needed when compiling for 68k.
-
- 4/28/97 The latest word from Apple is "The UpTime call will not be
- implemented on earlier PowerPCs under Tempo (Mac OS 8). That was the
- plan under Maxwell, but is no longer being considered."
-
- REFERENCE:
- TechNote 1083 Weak-linking to a Code Fragment Manager-based shared library
- http://devworld.apple.com/dev/technotes/tn/tn1083.html
-
- HISTORY:
- 5/8/96 dgp Wrote the MEX routine Secs.c.
- dhb Changed name to GetSecs, cosmetic editing.
- dgp Use UpTime if available.
- 6/6/96 dgp Omit DriverServicesLib calls when compiling for 68K.
- 1/26/97 dgp minor changes to allow successful 68K compile.
- 1/26/97 dgp extracted most of the code from GetSecs.c to create this new VideoToolbox
- Seconds.c, to make this good timebase more widely available.
- 2/9/97 dgp corrected function name in error message.
- 3/19/97 dgp minor tuning of the floating point arithmetic
- 7/9/97 dgp Simplified the test for availability of UpTime, based on TN1083.
- */
- #include "VideoToolbox.h"
- #if GENERATINGCFM
- #ifndef __CODEFRAGMENTS__
- #include <CodeFragments.h>
- #endif
- #endif
-
- typedef UnsignedWide AbsoluteTime; // Types.h
- typedef UnsignedWide Nanoseconds; // DriverServices.h
- extern AbsoluteTime UpTime(void); // DriverServices.h
- extern Nanoseconds AbsoluteToNanoseconds(AbsoluteTime absoluteTime);// DriverServices.h
-
- double Seconds(void)
- {
- static Boolean firstTime=1,upTimeAvailable=0;
- double s;
-
- if(firstTime){
- long version;
-
- // Make sure Microseconds trap is available.
- Gestalt(gestaltSystemVersion,&version);
- if(version<0x700)PrintfExit("%s: your System is too old; we need at least System 7.\n",__FILE__);
-
- // Is UpTime available?
- // The UpTime glue is in the DriverServicesLib shared library, which is
- // weak-linked, so we must load it before using it. If we fail,
- // we mustn't try to access the library's exports.
- // upTimeAvailable=IsDriverServicesLibAvailable();
- // In principle 68K code could call the PPC UpTime routine, but that would
- // require going through a UPP, which I haven't bothered with here. So we
- // play safe and only call UpTime from PPC code. This restriction won't affect
- // fat applications since they always run native.
- #if GENERATINGCFM && GENERATINGPOWERPC
- upTimeAvailable= (Ptr)UpTime!=(Ptr)kUnresolvedCFragSymbolAddress;
- #else
- upTimeAvailable=0;
- #endif
- firstTime=0;
- }
- if(upTimeAvailable){
- #if GENERATINGCFM && GENERATINGPOWERPC
- AbsoluteTime elapsedTime;
- Nanoseconds elapsedNanoseconds; // an UnsignedWide integer
-
- elapsedTime=UpTime();
- elapsedNanoseconds=AbsoluteToNanoseconds(elapsedTime);
- // NOTE: 4294967296.0 == (double)0x10000*0x10000
- s=elapsedNanoseconds.lo+4294967296.0*elapsedNanoseconds.hi;
- s/=1e9;
- #endif
- }else{
- UnsignedWide microTicks;
-
- Microseconds(µTicks);
- s=microTicks.lo+4294967296.0*microTicks.hi;
- s*=1e-6;
- }
- return s;
- }
-
- /*
- Boolean IsDriverServicesLibAvailable(void)
- {
- long error;
- Boolean isAvailable;
-
- if(1){
- // This extra test isn't strictly necessary.
- // However, calling Gestalt is fast, whereas calling GetSharedLibrary requires
- // a disk access, so we only call GetSharedLibrary if we expect it to succeed.
- Boolean pci;
- long value,version;
- #define gestaltNameRegistryVersion 'nreg' // support old Gestalt.h header
-
- error=Gestalt(gestaltNameRegistryVersion,&value);
- pci=!error; // are there PCI slots?
- Gestalt(gestaltSystemVersion,&version);
- isAvailable=pci;
- }
- #if GENERATINGPOWERPC && CFMSYSTEMCALLS
- if(isAvailable){
- // The DriverServicesLib shared library is
- // weak-linked, so we must load it before using it. If we fail,
- // we mustn't try to access the library's exports.
- CFragConnectionID connID;
- Ptr mainAddr;
- Str255 errorMessage;
- long value;
-
- error=Gestalt(gestaltCFMAttr,&value); // Code Fragment Manager?
- if(!error)error=GetSharedLibrary((ConstStr63Param)"\pDriverServicesLib"
- ,kAnyCFragArch,kFindCFrag,&connID,&mainAddr,errorMessage);
- isAvailable=!error;
- if(error)printf("WARNING: IsDriverServicesLibAvailable: GetSharedLibrary error=%ld, %s\n",(long)error,p2cstr(errorMessage));
- }
- #else
- isAvailable=0;
- #endif
- return isAvailable;
- }
- */